package com.hluck.goodweatherapp.ui;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

import com.baidu.location.BDLocation;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.hluck.goodweatherapp.R;
import com.hluck.goodweatherapp.adapter.DailyAdapter;
import com.hluck.goodweatherapp.adapter.HourlyAdapter;
import com.hluck.goodweatherapp.adapter.LifestyleAdapter;
import com.hluck.goodweatherapp.adapter.OnClickItemCallback;
import com.hluck.goodweatherapp.data.Constant;
import com.hluck.goodweatherapp.data.bean.AirResponse;
import com.hluck.goodweatherapp.data.bean.HourlyResponse;
import com.hluck.goodweatherapp.data.bean.LocationData;
import com.hluck.goodweatherapp.data.bean.WeatherData;
import com.hluck.goodweatherapp.data.bean.WeatherIndexResponse;
import com.hluck.goodweatherapp.data.bean.WeekWeather;
import com.hluck.goodweatherapp.databinding.ActivityMainBinding;
import com.hluck.goodweatherapp.databinding.DialogDailyDetailBinding;
import com.hluck.goodweatherapp.databinding.DialogHourlyDetailBinding;
import com.hluck.goodweatherapp.location.GoodLocation;
import com.hluck.goodweatherapp.location.LocationCallback;
import com.hluck.goodweatherapp.location.MyLocationListener;
import com.hluck.goodweatherapp.utils.CityDialog;
import com.hluck.goodweatherapp.utils.EasyDate;
import com.hluck.goodweatherapp.utils.GlideUtils;
import com.hluck.goodweatherapp.utils.LogUtils;
import com.hluck.goodweatherapp.utils.MVUtils;
import com.hluck.goodweatherapp.viewmodel.MainViewModel;
import com.hluck.mvvmlibrary.base.NetworkActivity;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class MainActivity extends NetworkActivity<ActivityMainBinding> implements LocationCallback,CityDialog.SelectedCityCallback {

    private static final String TAG = "MainActivity";

    //权限数组
    private final String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.WRITE_EXTERNAL_STORAGE};
    //请求权限意图
    private ActivityResultLauncher<String[]> requestPermissionIntent;

    //菜单
    private Menu mMenu;
    //城市信息来源标识：0：定位，1：切换城市
    private int cityFlag = 0;

    private GoodLocation goodLocation;

    private MainViewModel viewModel;

    private String mCityName;
    private boolean isRefresh;

    //城市弹窗
    private CityDialog cityDialog;

    SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");
    SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm");

    private final List<WeekWeather.DailyWeather> dailyWeathers = new ArrayList<>();
    private final DailyAdapter dailyAdapter = new DailyAdapter(dailyWeathers);

    private final List<WeatherIndexResponse.Index> dailyIndexes = new ArrayList<>();
    private final LifestyleAdapter lifestyleAdapter = new LifestyleAdapter(dailyIndexes);

    private final List<HourlyResponse.HourlyBean> hourlyBeanList = new ArrayList<>();
    private final HourlyAdapter hourlyAdapter = new HourlyAdapter(hourlyBeanList);

    private ActivityResultLauncher<Intent> jumpActivityIntent;


    @RequiresApi(api = Build.VERSION_CODES.M)
    private void initView(){
        setToolbarMoreIconCustom(viewBinding.materialToolbar);
        viewBinding.rvDaily.setLayoutManager(new LinearLayoutManager(this));
        dailyAdapter.setOnClickItemCallback(new OnClickItemCallback() {
            @Override
            public void onItemClick(int position) {
                showDailyDetailDialog(dailyWeathers.get(position));
            }
        });
        viewBinding.rvDaily.setAdapter(dailyAdapter);

        viewBinding.rvLifestyle.setLayoutManager(new LinearLayoutManager(this));
        viewBinding.rvLifestyle.setAdapter(lifestyleAdapter);

        //逐小时天气预报列表
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        viewBinding.rvHourly.setLayoutManager(linearLayoutManager);

        hourlyAdapter.setClickItemCallback(new OnClickItemCallback() {
            @Override
            public void onItemClick(int position) {
                showHourlyDetailDialog(hourlyBeanList.get(position));
            }
        });

        viewBinding.rvHourly.setAdapter(hourlyAdapter);

        viewBinding.layRefresh.setOnRefreshListener(() -> {
            LogUtils.logE("layRefresh");
            if (mCityName == null) {
                viewBinding.layRefresh.setRefreshing(false);
                return;
            }
            isRefresh = true;
            viewModel.searchCity(mCityName,false);
        });

        viewBinding.layScroll.setOnScrollChangeListener((View.OnScrollChangeListener) (v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
            if (scrollY > oldScrollY) {
                //getMeasuredHeight() 表示控件的绘制高度
                if (scrollY > viewBinding.layScrollHeight.getMeasuredHeight()) {
                    viewBinding.materialToolbar.setTitle((mCityName == null ? "城市天气" : mCityName));
                }
            } else if (scrollY < oldScrollY) {
                if (scrollY < viewBinding.layScrollHeight.getMeasuredHeight()) {
                    //改回原来的
                    viewBinding.materialToolbar.setTitle("城市天气");
                }
            }
        });

    }

    /**
     * 显示天气预报详情
     * @param dailyBean
     */
    private void showDailyDetailDialog(WeekWeather.DailyWeather dailyBean) {
        BottomSheetDialog dialog = new BottomSheetDialog(MainActivity.this);
        DialogDailyDetailBinding detailBinding = DialogDailyDetailBinding.inflate(LayoutInflater.from(MainActivity.this), null, false);
        //关闭弹窗
        detailBinding.ivClose.setOnClickListener(v -> dialog.dismiss());
        //设置数据显示
        detailBinding.toolbarDaily.setTitle(String.format("%s   %s", dailyBean.getFxDate(), EasyDate.getWeek(dailyBean.getFxDate())));
        detailBinding.toolbarDaily.setSubtitle("天气预报详情");
        detailBinding.tvTmpMax.setText(String.format("%s℃", dailyBean.getTempMax()));
        detailBinding.tvTmpMin.setText(String.format("%s℃", dailyBean.getTempMin()));
        detailBinding.tvUvIndex.setText(dailyBean.getUvIndex());
        detailBinding.tvCondTxtD.setText(dailyBean.getTextDay());
        detailBinding.tvCondTxtN.setText(dailyBean.getTextNight());
        detailBinding.tvWindDeg.setText(String.format("%s°", dailyBean.getWind360Day()));
        detailBinding.tvWindDir.setText(dailyBean.getWindDirDay());
        detailBinding.tvWindSc.setText(String.format("%s级", dailyBean.getWindScaleDay()));
        detailBinding.tvWindSpd.setText(String.format("%s公里/小时", dailyBean.getWindSpeedDay()));
        detailBinding.tvCloud.setText(String.format("%s%%", dailyBean.getCloud()));
        detailBinding.tvHum.setText(String.format("%s%%", dailyBean.getHumidity()));
        detailBinding.tvPres.setText(String.format("%shPa", dailyBean.getPressure()));
        detailBinding.tvPcpn.setText(String.format("%smm", dailyBean.getPrecip()));
        detailBinding.tvVis.setText(String.format("%skm", dailyBean.getVis()));
        dialog.setContentView(detailBinding.getRoot());
        dialog.show();
    }

    /**
     * 注册意图
     */
    @Override
    public void onRegister() {
        //请求权限意图
        requestPermissionIntent = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), result -> {
            boolean fineLocation = Boolean.TRUE.equals(result.get(Manifest.permission.ACCESS_FINE_LOCATION));
            boolean writeStorage = Boolean.TRUE.equals(result.get(Manifest.permission.WRITE_EXTERNAL_STORAGE));
            if (fineLocation && writeStorage) {
                //权限已经获取到，开始定位
                startLocation();
            }
        });

        jumpActivityIntent = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),result -> {
            if (result.getResultCode() == RESULT_OK && result.getData() != null){
                //获取上个页面返回的数据
                String city = result.getData().getStringExtra(Constant.CITY_RESULT);
                //检查返回的城市，如果返回的城市是当前定位城市，并且当前定位标志为0，则不需要请求
                if (city.equals(MVUtils.getString(Constant.LOCATION_CITY)) && cityFlag == 0){
                    LogUtils.logD("onRegister: 管理城市页面返回不需要进行天气查询");
                    return;
                }
                //反之就直接调用选中城市的方法进行城市天气搜索
                LogUtils.logD("onRegister: 管理城市页面返回进行天气查询");
                selectedCity(city);
            }
        });
    }

    private void updateBgImage(boolean useBing,String imgUrl){
        if (useBing && !imgUrl.isEmpty()){
            GlideUtils.loadImg(this,imgUrl,viewBinding.layRoot);
        } else {
            viewBinding.layRoot.setBackground(ContextCompat.getDrawable(this,R.drawable.img_5));
        }
    }

    /**
     * 初始化
     */
    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onCreate() {
        setFullScreenImmersion();
        initLocation();
        requestPermission();
        initView();
        viewModel = new ViewModelProvider(this).get(MainViewModel.class);
        //获取城市数据
        viewModel.getAllCity();
    }

    /**
     * 数据观察
     */
    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onObserveData() {
        if (viewModel != null) {
            //城市数据返回
            viewModel.searchLiveData.observe(this, searchCityResponse -> {
                Log.d(TAG, "searchCityResponse -> code: " + searchCityResponse.getCode());
                List<LocationData.Location> location = searchCityResponse.getLocation();
                if (location != null && location.size() > 0) {
                    String id = location.get(0).getId();
                    Log.d("TAG", "城市ID: " + id);
                    //根据cityFlag设置重新定位菜单项是否显示
                    mMenu.findItem(R.id.item_relocation).setVisible(cityFlag == 1);

                    //检查到正在刷新
                    if (isRefresh){
                        showMsg("刷新完成");
                        viewBinding.layRefresh.setRefreshing(false);
                        isRefresh = false;
                    }

                    if (id != null){
                        //通过城市ID查询城市实时天气
                        viewModel.searchWeather(id);
                        //通过城市ID查询天气预报
                        viewModel.dailyWeather(id);
                        //通过城市ID查询生活指数
                        viewModel.lifeStyle(id);
                        //通过城市ID查询逐小时天气预报
                        viewModel.hourlyWeather(id);
                        //通过城市ID查询空气质量
                        viewModel.airWeather(id);
                    }
                }
            });

            //实况天气
            viewModel.weatherLiveData.observe(this,weatherData -> {
                WeatherData.NowData now = weatherData.getNow();
                if (now != null){
                    viewBinding.tvWeek.setText(EasyDate.getTodayOfWeek());
                    viewBinding.tvWeatherInfo.setText(now.getText());
                    viewBinding.tvTemp.setText(now.getTemp());

                    String time = EasyDate.updateTime(weatherData.getUpdateTime());

                    viewBinding.tvUpdateTime.setText(String.format("最近更新时间：%s%s", EasyDate.showTimeInfo(time), time));
                    viewBinding.tvWindDirection.setText("风向     " + now.getWindDir());
                    viewBinding.tvWindPower.setText("风力     " + now.getWindScale() + "级");
                    viewBinding.wwBig.startRotate();
                    viewBinding.wwSmall.startRotate();
                }
            });

            //天气预报返回
            viewModel.weekWeatherLiveData.observe(this,dailyWeather -> {
                List<WeekWeather.DailyWeather> weatherList = dailyWeather.getDaily();
                Log.d(TAG,"weatherList size:"+weatherList.size());
                if (weatherList != null){
                    if (dailyWeathers.size() > 0) {
                        dailyWeathers.clear();
                    }
                    dailyWeathers.addAll(weatherList);
                    dailyAdapter.notifyDataSetChanged();
                    //设置当天最高温和最低温
                    viewBinding.tvHeight.setText(String.format("%s℃ ~ ",weatherList.get(0).getTempMax()));
                    viewBinding.tvLow.setText(String.format("%s℃",weatherList.get(0).getTempMin()));
                }
            });

            viewModel.lifeStyleLiveData.observe(this,lifeStyle -> {
                List<WeatherIndexResponse.Index> daily = lifeStyle.getDaily();
                if (daily != null){
                    Log.d(TAG,"daily size:"+daily.size());
                    if (dailyIndexes.size() > 0){
                        dailyIndexes.clear();
                    }
                    dailyIndexes.addAll(daily);
                    lifestyleAdapter.notifyDataSetChanged();
                }
            });

            viewModel.cityMutableLiveData.observe(this,provinces -> {
                Log.d(TAG,"获取到城市数据了！"+provinces);
                cityDialog = CityDialog.getInstance(this,provinces);
                cityDialog.setSelectedCityCallback(this);
            });

            //错误信息返回
            viewModel.failed.observe(this,this::showLongMsg);

            viewModel.hourlyResponseMutableLiveData.observe(this,hourlyResponse -> {
                List<HourlyResponse.HourlyBean> hourly = hourlyResponse.getHourly();
                if (hourly != null) {
                    if (hourlyBeanList.size() > 0) hourlyBeanList.clear();
                    hourlyBeanList.addAll(hourly);
                    hourlyAdapter.notifyDataSetChanged();
                }
            });

            viewModel.airResponseMutableLiveData.observe(this,airResponse -> {
                dismissLoadingDialog();
                AirResponse.NowBean now = airResponse.getNow();
                if (now == null) return;
                viewBinding.rpbAqi.setMaxProgress(300);
                viewBinding.rpbAqi.setMinText("0");
                viewBinding.rpbAqi.setMinTextSize(20f);
                viewBinding.rpbAqi.setMaxText("300");
                viewBinding.rpbAqi.setMaxTextSize(20f);
                viewBinding.rpbAqi.setProgress(Float.parseFloat(now.getAqi()));//当前进度
                viewBinding.rpbAqi.setArcBgColor(getColor(R.color.arc_bg_color));//圆弧的颜色
                viewBinding.rpbAqi.setProgressColor(getColor(R.color.arc_progress_color));//进度圆弧的颜色
                viewBinding.rpbAqi.setFirstText(now.getCategory());//空气质量描述 取值范围：优，良，轻度污染，中度污染，重度污染，严重污染
                viewBinding.rpbAqi.setFirstTextSize(24f);//第一行文本的字体大小
                viewBinding.rpbAqi.setSecondText(now.getAqi());//空气质量值
                viewBinding.rpbAqi.setSecondTextSize(34f);//第二行文本的字体大小
                viewBinding.rpbAqi.setMinText("0");
                viewBinding.rpbAqi.setMinTextColor(getColor(R.color.arc_progress_color));

                viewBinding.tvAirInfo.setText(String.format("空气%s", now.getCategory()));

                viewBinding.tvPm10.setText(now.getPm10());//PM10
                viewBinding.tvPm25.setText(now.getPm2p5());//PM2.5
                viewBinding.tvNo2.setText(now.getNo2());//二氧化氮
                viewBinding.tvSo2.setText(now.getSo2());//二氧化硫
                viewBinding.tvO3.setText(now.getO3());//臭氧
                viewBinding.tvCo.setText(now.getCo());//一氧化碳
            });
        }
    }

    private void showHourlyDetailDialog(HourlyResponse.HourlyBean hourlyBean) {
        BottomSheetDialog dialog = new BottomSheetDialog(MainActivity.this);
        DialogHourlyDetailBinding detailBinding = DialogHourlyDetailBinding.inflate(LayoutInflater.from(MainActivity.this), null, false);
        //关闭弹窗
        detailBinding.ivClose.setOnClickListener(v -> dialog.dismiss());
        //设置数据显示
        String time = EasyDate.updateTime(hourlyBean.getFxTime());
        detailBinding.toolbarHourly.setTitle(EasyDate.showTimeInfo(time) + time);
        detailBinding.toolbarHourly.setSubtitle("逐小时预报详情");
        detailBinding.tvTmp.setText(String.format("%s℃", hourlyBean.getTemp()));
        detailBinding.tvCondTxt.setText(hourlyBean.getText());
        detailBinding.tvWindDeg.setText(String.format("%s°", hourlyBean.getWind360()));
        detailBinding.tvWindDir.setText(hourlyBean.getWindDir());
        detailBinding.tvWindSc.setText(String.format("%s级", hourlyBean.getWindScale()));
        detailBinding.tvWindSpd.setText(String.format("公里/小时%s", hourlyBean.getWindSpeed()));
        detailBinding.tvHum.setText(String.format("%s%%", hourlyBean.getHumidity()));
        detailBinding.tvPres.setText(String.format("%shPa", hourlyBean.getPressure()));
        detailBinding.tvPop.setText(String.format("%s%%", hourlyBean.getPop()));
        detailBinding.tvDew.setText(String.format("%s℃", hourlyBean.getDew()));
        detailBinding.tvCloud.setText(String.format("%s%%", hourlyBean.getCloud()));
        dialog.setContentView(detailBinding.getRoot());
        dialog.show();
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    public void setToolbarMoreIconCustom(Toolbar toolbar) {
        if (toolbar == null) {
            return;
        }
        toolbar.setTitle("城市天气");
        Drawable moreIcon = ContextCompat.getDrawable(toolbar.getContext(), R.drawable.ic_round_add_32);
        if (moreIcon != null) toolbar.setOverflowIcon(moreIcon);
        setSupportActionBar(toolbar);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main,menu);
        mMenu = menu;
        //根据cityFlag设置重新定位菜单项是否显示
        mMenu.findItem(R.id.item_relocation).setVisible(cityFlag == 1);
        //根据使用必应壁纸的状态，设置item项是否选中
        mMenu.findItem(R.id.item_bing).setChecked(MVUtils.getBoolean(Constant.USED_BING));
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        Log.d(TAG, "切换城市");
        switch (item.getItemId()){
            case R.id.item_switching_cities:
                if (cityDialog != null) cityDialog.show();
                break;
            case R.id.item_relocation:
                startLocation();
                break;
            case R.id.item_bing:
                item.setChecked(!item.isChecked());
                MVUtils.put(Constant.USED_BING,item.isChecked());
                String bingUrl = MVUtils.getString(Constant.BING_URL);
                LogUtils.logE("onOptionsItemSelected -> bingUrl:"+bingUrl);
                //更新壁纸
                updateBgImage(item.isChecked(),bingUrl);
                break;
            case R.id.item_manage_city:
                jumpActivityIntent.launch(new Intent(mContext,ManageCityActivity.class));
                break;
        }
        return true;
    }


    @Override
    protected void onResume() {
        super.onResume();
        //更新壁纸
        updateBgImage(MVUtils.getBoolean(Constant.USED_BING),MVUtils.getString(Constant.BING_URL));
    }

    /**
     * 请求权限
     */
    @RequiresApi(api = Build.VERSION_CODES.M)
    private void requestPermission() {
        //因为项目的最低版本API是23，所以肯定需要动态请求危险权限，只需要判断权限是否拥有即可
        if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                || checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            //开始权限请求
            requestPermissionIntent.launch(permissions);
            return;
        }
        //开始定位
        startLocation();
    }


    /**
     * 初始化定位
     */
    private void initLocation() {
        goodLocation = GoodLocation.getInstance(this);
        goodLocation.setCallback(this);
    }

    /**
     * 开始定位
     */
    private void startLocation() {
        cityFlag = 0;
       goodLocation.startLocation();
    }

    /**
     * 接收定位信息
     * @param bdLocation 定位数据
     */
    @Override
    public void onReceiveLocation(BDLocation bdLocation) {
        showLoadingDialog();
        double latitude = bdLocation.getLatitude();    //获取纬度信息
        double longitude = bdLocation.getLongitude();    //获取经度信息
        float radius = bdLocation.getRadius();    //获取定位精度，默认值为0.0f
        String coorType = bdLocation.getCoorType();
        //获取经纬度坐标类型，以LocationClientOption中设置过的坐标类型为准
        int errorCode = bdLocation.getLocType();//161  表示网络定位结果
        //获取定位类型、定位错误返回码，具体信息可参照类参考中BDLocation类中的说明
        String addr = bdLocation.getAddrStr();    //获取详细地址信息
        String country = bdLocation.getCountry();    //获取国家
        String province = bdLocation.getProvince();    //获取省份
        String city = bdLocation.getCity();    //获取城市
        String district = bdLocation.getDistrict();    //获取区县
        String street = bdLocation.getStreet();    //获取街道信息
        String locationDescribe = bdLocation.getLocationDescribe();    //获取位置描述信息
//        viewBinding.tvAddressDetail.setText(addr);//设置文本显示
        Log.d(TAG, "addr: " + addr);
        if (viewModel != null && district != null) {
            mCityName = district;
            //保存定位城市
            MVUtils.put(Constant.LOCATION_CITY,district);
            //保存到我的城市数据表中
            viewModel.addMyCityData(district);
            //显示当前定位的城市
            viewBinding.tvCity.setText(district);
            //搜索城市
            viewModel.searchCity(district,false);
        } else {
            Log.e("TAG", "district: " + district);
        }
    }

    @Override
    public void selectedCity(String cityName) {
        cityFlag = 1;
        mCityName = cityName;
        //搜索城市
        viewModel.searchCity(cityName,false);
        //显示所选城市
        viewBinding.tvCity.setText(cityName);
    }
}